home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / dev / c / vbcc.lha / vbcc / pasm / pass.c < prev    next >
C/C++ Source or Header  |  1998-02-17  |  13KB  |  474 lines

  1. /* $VER: pasm pass.c V0.8 (14.02.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v0.8 (14.02.98) phx
  16.  *      Alignment list for each section. This fixes the problems
  17.  *      with optimizations.
  18.  * v0.7 (02.01.98) phx
  19.  *      Allow more than two assembler passes, as required for
  20.  *      optimizations.
  21.  * v0.6 (26.10.97) phx
  22.  *      Bug in conditional assembly fixed.
  23.  *      @object and @function symbols are always defined before
  24.  *      pass 1 is executed.
  25.  * v0.5 (12.10.97) phx
  26.  *      Support for user symbol definitions by -D option.
  27.  *      The opcode field is automatically converted to lower case,
  28.  *      so upper case directives and instructions are also allowed.
  29.  * v0.3 (10.04.97) phx
  30.  *      Some vbcc-specific changes.
  31.  * v0.2 (25.03.97) phx
  32.  *      Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  33.  *      or ELF output format may be selected. ELF is default for all
  34.  *      currently supported platforms. PPCasm supports nine different
  35.  *      relocation types (there are much more...).
  36.  *      Compiles and works also under NetBSD/amiga (68k).
  37.  *      Changed function declaration to 'new style' in all sources
  38.  *      (to avoid problems with '...' for example).
  39.  * v0.1 (11.03.97) phx
  40.  *      First test version with all PowerPC instructions and most
  41.  *      important directives. Only raw, absolute output.
  42.  * v0.0 (15.02.97) phx
  43.  *      File created.
  44.  */
  45.  
  46.  
  47. #define PASS_C
  48. #include "ppcasm.h"
  49.  
  50.  
  51. void exec_pass1(struct GlobalVars *);
  52. void pass1(struct GlobalVars *,struct SourceText *,
  53.            struct MacroParams *,struct SourceThread *);
  54. struct SourceText *include_source(struct GlobalVars *,char *);
  55. void exec_pass2(struct GlobalVars *);
  56. void pass2(struct GlobalVars *,struct SourceText *,
  57.            struct MacroParams *,struct SourceThread *);
  58. struct SourceText *get_source(struct GlobalVars *);
  59.  
  60. static char *insert_macro_params(struct GlobalVars *,struct ParsedLine *,
  61.                                  char *,struct MacroParams *);
  62. static char *readline(struct GlobalVars *,struct ParsedLine *,char *);
  63. static char *getlabel(struct GlobalVars *,char *);
  64. static struct SourceText *add_source(struct GlobalVars *,char *,char *,long);
  65. static void prepare_sections(struct GlobalVars *);
  66.  
  67.  
  68.  
  69. void exec_pass1(struct GlobalVars *gv)
  70. {
  71.   struct Symbol *sym;
  72.   char asmname[20];
  73.   char **p,*xmnemobuf,*usrdefbuf;
  74.   size_t xmsize=0,udsize=0;
  75.   struct UserDefine *nextudn;
  76.   struct UserDefine *udn = (struct UserDefine *)gv->userdeflist.first;
  77.   struct Section dummySec;
  78.  
  79.   sprintf(asmname,PNAME "_V%d.%02d",VERSION,REVISION);
  80.   memset(&dummySec,0,sizeof(struct Section));
  81.   gv->csect = &dummySec;  /* to avoid SEGVs during start up */
  82.   sym = add_symbol(gv,asmname,SYM_ABS,0);
  83.   sym->bind = SYMB_LOCAL;
  84.   gv->lcsym = add_symbol(gv,"$",SYM_RELOC,0);
  85.   gv->nargsym = add_symbol(gv,"$NARG",SYM_ABS,0);
  86.   add_symbol(gv,"@object",SYM_ABS,1);
  87.   add_symbol(gv,"@function",SYM_ABS,2);
  88.   gv->ifcond[0] = TRUE;
  89.  
  90.   pass1(gv,add_source(gv,"<standard sections>",stdsects,
  91.         strlen(stdsects)),NULL,NULL);
  92.  
  93.   if (!gv->noregsymbols)
  94.     pass1(gv,add_source(gv,"<standard definitions>",stdsets,
  95.           strlen(stdsets)),NULL,NULL);
  96.  
  97.   while (nextudn = (struct UserDefine *)udn->n.next) {
  98.     udsize += strlen(udn->line);
  99.     udn = nextudn;
  100.   }
  101.   if (udsize) {
  102.     usrdefbuf = alloc(udsize+1);
  103.     *usrdefbuf = 0;
  104.     while (udn = (struct UserDefine *)remhead(&gv->userdeflist)) {
  105.       strcat(usrdefbuf,udn->line);
  106.       free(udn->line);
  107.       free(udn);
  108.     }
  109.     gv->usrdefs = TRUE;
  110.     pass1(gv,add_source(gv,"<user definitions>",usrdefbuf,udsize),
  111.           NULL,NULL);
  112.   }
  113.  
  114.   if (!gv->noextmnemo) {
  115.     p = xmnemos;
  116.     while (*p) {
  117.       xmsize += strlen(*p);
  118.       p++;
  119.     }
  120.     xmnemobuf = alloc(xmsize+1);
  121.     *xmnemobuf = 0;
  122.     p = xmnemos;
  123.     while (*p) {
  124.       strcat(xmnemobuf,*p);
  125.       p++;
  126.     }
  127.     pass1(gv,add_source(gv,"<extended mnemonics>",xmnemobuf,xmsize),
  128.           NULL,NULL);
  129.   }
  130.  
  131.   pass1(gv,include_source(gv,gv->source_name),NULL,NULL);
  132.   if (gv->vc) {
  133.     activate_section(gv,(struct Section *)gv->sectionlist.first);
  134.     alignment(gv,2);
  135.     pcadd(gv,4);
  136.   }
  137. }
  138.  
  139.  
  140. void pass1(struct GlobalVars *gv,struct SourceText *srctxt,
  141.            struct MacroParams *macro,struct SourceThread *prev_st)
  142. /* Assembler Pass 1 */
  143. {
  144.   struct SourceThread st;
  145.   unsigned long nlines = srctxt->nlines;
  146.   char *lp,c;
  147.   struct ParsedLine *pl = srctxt->plin;
  148.  
  149.   /* init SourceThread structure */
  150.   st.prev = prev_st;
  151.   st.macro = macro;
  152.   st.csource = srctxt;
  153.   st.srcptr = srctxt->text;  /* current source pointer */
  154.   st.line = 1;
  155.   st.macskip = NULL;
  156.   gv->cthread = &st;  /* set current source thread */
  157.  
  158.   while (nlines--) {
  159.     gv->absline++;
  160.     pl->lineptr = st.lineptr = st.srcptr;
  161.  
  162.     /* get next line of source text */
  163.     if (macro && gv->ifcond[gv->iflevel]) {  /* insert macro parameters? */
  164.       st.srcptr = insert_macro_params(gv,pl,st.srcptr,macro);
  165.     }
  166.     else {
  167.       st.srcptr = readline(gv,pl,st.srcptr);
  168.     }
  169.     lp = gv->linebuf;
  170.  
  171.     /* evaluate label field */
  172.     lp = getlabel(gv,lp);
  173.     if (*gv->strbuf)
  174.       if (!st.macskip && gv->ifcond[gv->iflevel])
  175.         add_symbol(gv,gv->strbuf,SYM_RELOC,gv->csect->pc);
  176.     lp = skipspaces(lp);
  177.  
  178.     /* evaluate opcode field */
  179.     lp = getsymbol(gv,lp);
  180.     if (*gv->strbuf) {
  181.       lower_case(gv->strbuf);  /* convert opcode to lower case */
  182.  
  183.       if (st.macskip) {  /* macros */
  184.         if (!strcmp(gv->strbuf,".endm")) {
  185.           st.macskip->nlines = gv->absline - st.macskip->nlines;
  186.           add_macro(gv,st.macskip);
  187.           st.macskip = NULL;
  188.         }
  189.       }
  190.  
  191.       else if (!gv->ifcond[gv->iflevel]) {  /* conditional assembly */
  192.         if (!strncmp(gv->strbuf,".if",3))
  193.           gv->ifignore++;
  194.         else if (!strcmp(gv->strbuf,".else")) {
  195.           if (gv->ifignore == 0)
  196.             gv->ifcond[gv->iflevel] = TRUE;
  197.         }
  198.         else if (!strcmp(gv->strbuf,".endif")) {
  199.           if (gv->ifignore)
  200.             gv->ifignore--;
  201.           else
  202.             gv->iflevel--;
  203.         }
  204.       }
  205.  
  206.       else {  /* search opcode */
  207.         c = *lp;  /* branch hint given? */
  208.         if (c=='+') {
  209.           lp++;
  210.           pl->branch_hint = 1;
  211.         }
  212.         else if (c=='-') {
  213.           lp++;
  214.           pl->branch_hint = -1;
  215.         }
  216.         search_opcode(gv,pl,gv->strbuf,skipspaces(lp));
  217.       }
  218.     }
  219.  
  220.     if (!(pl->flags&PLF_NONEWLINE))
  221.       st.line++;
  222.     ++pl;
  223.   }
  224.   gv->cthread = prev_st;
  225. }
  226.  
  227.  
  228. static char *insert_macro_params(struct GlobalVars *gv,struct ParsedLine *pl,
  229.                                  char *s,struct MacroParams *mp)
  230. {
  231.   char **par = mp->param;
  232.   char c,callidbuf[16];
  233.   char *pp,*d=gv->linebuf;
  234.   int n;
  235.  
  236.   do {
  237.     if ((c=*s++) == '\\') {
  238.       if (*s>='0' && *s<='9') {  /* macro parameter? */
  239.         n = (int)(*s++ - '0');
  240.         if (pp = par[n]) {
  241.           while (*d++ = *pp++);  /* insert parameter */
  242.           d--;
  243.           continue;
  244.         }
  245.         else {
  246.           error(9,n);  /* reference to undefined macro parameter n */
  247.           continue;
  248.         }
  249.       }
  250.       else if (*s=='@') {  /* insert macro call id */
  251.         s++;
  252.         pp = callidbuf;
  253.         sprintf(pp,"$%d",(int)mp->call_id);
  254.         while (*d++ = *pp++);
  255.         d--;
  256.         continue;
  257.       }
  258.     }
  259.     *d++ = c;
  260.   }
  261.   while (c!=0 && c!=1);
  262.   if (c==1) {
  263.     *(--d) = 0;
  264.     pl->flags |= PLF_NONEWLINE;
  265.   }
  266.   return (s);
  267. }
  268.  
  269.  
  270. static char *readline(struct GlobalVars *gv,struct ParsedLine *pl,char *s)
  271. {
  272.   char c,*d = gv->linebuf;
  273.  
  274.   do {
  275.     c = *s++;
  276.     *d++ = c;
  277.   }
  278.   while (c!=0 && c!=1);
  279.   if (c==1) {
  280.     *(--d) = 0;
  281.     pl->flags |= PLF_NONEWLINE;
  282.   }
  283.   return (s);
  284. }
  285.  
  286.  
  287. static char *getlabel(struct GlobalVars *gv,char *s)
  288. /* read label